package actions;


import java.awt.event.ActionEvent;
import java.util.ArrayList;
import javax.swing.JTextPane;

import frame.AwesomeFrame;

/**
 * Handle actions made in column mode.
 * @author Ashley Polkinghorn
 *
 */
public class ColumnModeAction extends AwesomeKeyAction {
	
	public ColumnModeAction(String name) {
		super(name);
	}

	/**
	 * Handle key events in column mode. These are only different
	 * when text is selected.
	 */
	@Override
	public void actionPerformed(ActionEvent e) {

		String charString = e.getActionCommand();
		if(charString.length()<1) return;
		char character = charString.charAt(0);
		
		if(!((character < '\u007F' && character >= ' ') || character == '\b')) return;
		JTextPane pane = getTextPane(e);
		// move this disaster
		AwesomeFrame frame = (AwesomeFrame)pane.getParent().getParent().getParent().getParent().getParent().getParent();
		if(!frame.isInColumnMode) return;
		
		int highlightStart = pane.getSelectionStart();
		int highlightEnd = pane.getSelectionEnd();
		if(highlightStart == highlightEnd) return;
		
		
		String newline = "\n";
		String oldText = pane.getText().replaceAll("\r", "");
		
		// there is a selection, and it's either a block or a vertical line, or only one line
		// list of ends of lines (starts are the same as previous ends)
		ArrayList<Integer> lines = new ArrayList<Integer>();
		int index = oldText.indexOf(newline);
		while(index > 0)
		{
			lines.add(index);
			if(index < oldText.length()-1);
			index = oldText.indexOf(newline,index+1);
		}
		lines.add(oldText.length()-1);
		
		int size = lines.size();
		if (size < 1) return; // selection contained in one line =>no behavior change
		

		
		
		SelectedLocations loc = findLocations(lines, highlightStart, highlightEnd);
		String newText;
		ReplacementWithHighlighting r;
		if(character == '\u007F' || character == '\b')
		{
			//newText = delete(highlightStart, highlightEnd, oldText,lines,loc);
			r = replace(oldText,lines,loc,"", character);
			newText = r.replacement;
			newText += " ";
			r.highlightStart = newText.length() - 1;
		}
		else
		{
			String replacement = "";
			for(int i=loc.startChar;i<loc.endChar;i++)
			{
				replacement += character;
			}
			if(loc.startChar == loc.endChar) replacement+=character;
			r = replace(oldText,lines,loc,replacement, character);
			newText = r.replacement;
		}
	
		
		pane.setText(newText);
		pane.setSelectionStart(r.highlightStart);
		pane.setSelectionEnd(r.highlightStart+1);
		
	}
	
	/**
	 * Extracts information about the selection area in the textPane
	 * @param lines
	 * @param highlightStart
	 * @param highlightEnd
	 * @return
	 */
	private SelectedLocations findLocations(ArrayList<Integer> lines, int highlightStart, int highlightEnd)
	{
		/* Find selected start and end locations */
		SelectedLocations loc = new SelectedLocations();
		int index=0;
		
		int lastIndex=0;
		for (Integer endline : lines)
		{
			if(loc.startLine < 0)
			{
				if(endline >= highlightStart)
				{
					loc.startLine = index;
					loc.startChar = highlightStart - lastIndex;
				}
			}
			if(loc.endLine < 0)
			{
				if(endline >= highlightEnd-1)
				{
					loc.endLine = index;
					loc.endChar = highlightEnd - lastIndex;
				}
			}
			lastIndex = endline+1;
			index++;
		}
		if(loc.endChar < loc.startChar)
		{
			int tempSwap = loc.endChar;
			loc.endChar = loc.startChar;
			loc.startChar = tempSwap;
		}
		return loc;
	}
	
	/**
	 * Handles delete/backspace in column mode
	 * @param oldText text in pane
	 * @param lines list of indices of the file's newlines
	 * @param loc information about the selection in textPane
	 * @return
	 */
	private ReplacementWithHighlighting replace(String oldText, ArrayList<Integer> lines,SelectedLocations loc,String replacement, char character)
	{
		if(character == '\b' && loc.startChar == loc.endChar) // delete last
		{
			if(loc.startChar < 1)
			{
				ReplacementWithHighlighting r = new ReplacementWithHighlighting();
				r.replacement = oldText;
				r.highlightStart = oldText.length()-1;
				return r;
			}
			loc.startChar--;
		}
		int lastIndex=0;
		String newText = "";
		if(loc.startLine > 0)
		{
			lastIndex = lines.get(loc.startLine-1)+1;
			newText = oldText.substring(0,lastIndex);
		}
		int i=0;
		int highlightStart=0;
		for(i=loc.startLine;i<=loc.endLine;i++)
		{
			int thisIndex = lines.get(i)+1;
			newText += oldText.substring(lastIndex,lastIndex+loc.startChar);// +1 for newline
			newText += replacement;
			highlightStart = newText.length()-1;
			if(lastIndex+loc.endChar <= thisIndex)
			{
				newText += oldText.substring(lastIndex+loc.endChar, thisIndex);
			}
			lastIndex = thisIndex;
		}
		if((lines.size()>i))
			newText += oldText.substring(lastIndex);
		
		ReplacementWithHighlighting r = new ReplacementWithHighlighting();
		r.replacement = newText;
		r.highlightStart = highlightStart;
		return r;
	}
	
	/**
	 * Wrapper for replacement text with highlight index
	 * @author Ashley Polkinghorn
	 *
	 */
	private class ReplacementWithHighlighting
	{
		String replacement="";
		int highlightStart=0;
	}
	
	/**
	 * A class to store information about the selection in the textPane
	 * @author Ashley Polkinghorn
	 *
	 */
	private class SelectedLocations
	{
		/**
		 * The index of the line in which highlighting starts
		 */
		int startLine = -1;
		/**
		 * The highlighting's offset from the begging of the line
		 */
		int startChar = -1;
		/**
		 * The index of the line in which highlighting ends
		 */
		int endLine = -1;
		/**
		 * The highlight end's offset from the beginning of the line
		 */
		int endChar = -1;
		
		/**
		 * ToString shows all the member variables.
		 */
		public String toString()
		{
			return "startLine:"+startLine+"\nstartChar:"+startChar
					+"\nendLine:"+endLine+"\nendChar:"+endChar;
		}
	}
}
